package com.letv.ads.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;

import com.letv.adlib.managers.status.ad.AdStatusManager;
import com.letv.adlib.model.services.LetvGifDownloadManager;
import com.letv.adlib.model.services.LetvGifTask.GifLoadingListener;
import com.letv.adlib.sdk.types.AdElement;
import com.letv.adlib.sdk.types.AdElementMime;
import com.letv.ads.util.LogInfo;
import com.letv.android.sdk.R;

import java.io.InputStream;

public class AdGifView extends View implements IAdView {
    private static final String TAG = "AdGifView";
    /**
     * 默认为1秒
     */
    private static final int DEFAULT_MOVIE_DURATION = 1000;
    private static final int INTERVAL_MOVIE_DURATION = 100;

    private Movie mMovie;

    private long mMovieStart;

    private int mCurrentAnimationTime = 0;

    private float mLeft;

    private float mTop;

    private float mScaleX;
    private float mScaleY;
    private int mMeasuredMovieWidth;

    private int mMeasuredMovieHeight;

    private boolean mVisible = true;
    private boolean mHasClosed = false;

    private volatile boolean mPaused = false;
    private int mDuration;
    private AdMaterialLoadListener mAdMaterialLoadListener;
    private AdViewOnclickListenr mAdViewOnclickListenr;
    private AdPlayStateListener mAdPlayStateListener;
    private AdElementMime mAdInfo;

    public AdGifView(Context context) {
        this(context, null);
    }

    public AdGifView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AdGifView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initAttr(context, attrs, defStyle);
    }

    private void initAttr(Context context, AttributeSet attrs, int defStyle) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }
        // 从描述文件中读出gif的值，创建出Movie实例
        final TypedArray array = context.obtainStyledAttributes(attrs,
                R.styleable.AdGifView, 0, 0);
        int movieResourceId = array
                .getResourceId(R.styleable.AdGifView_gif, -1);
        mPaused = array.getBoolean(R.styleable.AdGifView_paused, false);
        array.recycle();
        if (movieResourceId != -1) {
            mMovie = Movie.decodeStream(getResources().openRawResource(
                    movieResourceId));
            if (null != mMovie) {
                mDuration = mMovie.duration();
                if (mDuration == 0) {
                    mDuration = DEFAULT_MOVIE_DURATION;
                }
            }
        }
    }

    public void setMovieInputStream(InputStream inputStream) {
        Movie movie = Movie.decodeStream(inputStream);
        setMovie(movie);
    }

    public void setMovieResourceId(int movieResourceId) {
        Movie movie = Movie.decodeStream(getResources().openRawResource(
                movieResourceId));
        setMovie(movie);
    }

    public void setMovie(Movie movie) {
        if (null != movie) {
            this.mMovie = movie;
            if (null != movie) {
                mDuration = movie.duration();
                if (mDuration == 0) {
                    mDuration = DEFAULT_MOVIE_DURATION;
                }
            }
            setPaused(false);
            requestLayout();
        }
    }

    public void setMovieFile(String filename) {
        Movie movie = Movie.decodeFile(filename);
        setMovie(movie);
    }

    public void setMovieData(byte[] data, int offset, int length) {
        Movie movie = Movie.decodeByteArray(data, offset, length);
        setMovie(movie);
    }

    public Movie getMovie() {
        return mMovie;
    }

    /**
     * 设置暂停
     * 
     * @param paused
     */
    public void setPaused(boolean paused) {
        if (mPaused != paused) {
            this.mPaused = paused;
            LogInfo.log(TAG, "setPaused paused=" + paused);
            if (null != mHandler) {
                if (paused) {
                    mHandler.removeMessages(0);
                } else {
                    mHandler.sendEmptyMessage(0);
                }
            }
        }
    }

    /**
     * 判断gif图是否停止了
     * 
     * @return
     */
    public boolean isPaused() {
        return this.mPaused;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        LogInfo.log(TAG, "onMeasure widthMeasureSpec=" + widthMeasureSpec
                + "  heightMeasureSpec=" + heightMeasureSpec + " mMovie="
                + mMovie);
        if (mMovie != null) {
            int movieWidth = mMovie.width();
            int movieHeight = mMovie.height();
            mMeasuredMovieWidth = MeasureSpec.getSize(widthMeasureSpec);
            mMeasuredMovieHeight = MeasureSpec.getSize(heightMeasureSpec);
            mScaleX = (float) mMeasuredMovieWidth / (float) movieWidth;
            mScaleY = (float) mMeasuredMovieHeight / (float) movieHeight;
            setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight);
        } else {
            setMeasuredDimension(getSuggestedMinimumWidth(),
                    getSuggestedMinimumHeight());
        }
        LogInfo.log(TAG, "onMeasure mScaleX=" + mScaleX + "  mScaleY="
                + mScaleY + " mMeasuredMovieHeight=" + mMeasuredMovieHeight
                + "  mMeasuredMovieHeight=" + mMeasuredMovieHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mLeft = (getWidth() - mMeasuredMovieWidth) / 2f;
        mTop = (getHeight() - mMeasuredMovieHeight) / 2f;
        mVisible = getVisibility() == View.VISIBLE;
        LogInfo.log(TAG, "onLayout mLeft=" + mLeft + " mTop=" + mTop
                + " mScaleX=" + mScaleX + "  mScaleY=" + mScaleY
                + " getWidth()=" + getWidth() + "  getHeight()=" + getHeight());
    }

    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (!mHandler.hasMessages(0)) {
                mHandler.sendEmptyMessageDelayed(0, INTERVAL_MOVIE_DURATION);
            }
            updateAnimationTime();
            invalidateView();
        }
    };

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // LogInfo.log(TAG, "onDraw mPaused=" + mPaused);
        if (mMovie != null) {
            if (!mPaused) {
                if (null != mHandler && !mHandler.hasMessages(0)) {
                    mHandler.sendEmptyMessage(0);
                }
            }
            drawMovieFrame(canvas);
        }
    }

    private void invalidateView() {
        if (mVisible) {
            invalidate();
        } else if (null != mHandler) {
            mHandler.removeMessages(0);
        }
    }

    private void updateAnimationTime() {
        mMovieStart = INTERVAL_MOVIE_DURATION + mMovieStart;
        // 算出需要显示第几帧
        mCurrentAnimationTime = (int) (mMovieStart % mDuration);
        mMovie.setTime(mCurrentAnimationTime);
    }

    private void drawMovieFrame(Canvas canvas) {
        // 设置要显示的帧，绘制即可
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.scale(mScaleX, mScaleY);
        mMovie.draw(canvas, mLeft / mScaleX, mTop / mScaleY);
        canvas.restore();
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        mVisible = visibility == View.VISIBLE;
        LogInfo.log(TAG, "onVisibilityChanged changedView=" + changedView
                + "  visibility=" + visibility);
        invalidateView();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        LogInfo.log(TAG, "onDetachedFromWindow ");
        if (null != mHandler) {
            mHandler.removeMessages(0);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.letv.ads.view.IAdView#showAD(com.letv.adlib.sdk.types.AdElementMime)
     */
    @Override
    public void showAD(final AdElementMime adInfo) {
        mAdInfo = adInfo;
        LetvGifDownloadManager.getInstance().startDownload(adInfo.mediaFileUrl,
                this, new GifLoadingListener() {
                    public void onLoadingComplete(String gifUri, View view,
                            byte[] data) {
                        if (AdElement.AdMediaType.DYNAMIC != adInfo.mediaFileType) {
                            return;
                        }
                        if (null != mAdMaterialLoadListener) {
                            mAdMaterialLoadListener.onLoadComplete();
                        }
                        LogInfo.log(TAG, "onLoadingComplete gifUri=" + gifUri
                                + "  view=" + view + " data=" + data);
                        if (null != view && null != data) {
                            if (null != mAdPlayStateListener) {
                                Bundle bundle = new Bundle();
                                bundle.putInt(KEY_STATE, PLAY_STATE_STARTED);
                                mAdPlayStateListener
                                        .onADPlayStateChange(bundle);
                            }
                            ((AdGifView) view).setMovieData(data, 0,
                                    data.length);
                            // 混合非播放器内广告控制重复曝光，其他广告不控制
                            if (!adInfo.hadExposed || !adInfo.isComplexAD()) {
                                adInfo.hadExposed = true;
                                /**
                                 * 曝光统计
                                 * */
                                AdStatusManager statusMgr = new AdStatusManager(
                                        adInfo);
                                statusMgr.onAdPlayStart();
                            }

                        }
                    }

                    @Override
                    public void onLoadingFailed(String imageUri, View view) {
                        if (null != mAdMaterialLoadListener) {
                            mAdMaterialLoadListener.onLoadFailed();
                        }
                    }
                });
        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mAdViewOnclickListenr) {
                    mAdViewOnclickListenr.onADClick(adInfo);
                }
            }
        });
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.letv.ads.view.IAdView#closeAD()
     */
    @Override
    public void closeAD() {
        if (mHasClosed) {
            return;
        } else {
            mHasClosed = true;
        }
        setVisibility(GONE);
        if (null != mAdInfo) {
            /**
             * 完成统计
             * */
            AdStatusManager statusMgr = new AdStatusManager(mAdInfo);
            statusMgr.onAdPlayComplete();
        }
    }

    /*
     * 
     * @see com.letv.ads.view.IAdView#setAdOnClickListener(com.letv.ads.view.
     * AdViewOnclickListenr)
     */
    @Override
    public void setAdOnClickListener(AdViewOnclickListenr adViewOnclickListenr) {
        mAdViewOnclickListenr = adViewOnclickListenr;
    }

    /*
     * 
     * @see
     * com.letv.ads.view.IAdView#setAdMaterialLoadListener(com.letv.ads.view
     * .IAdView.AdMaterialLoadListener)
     */
    @Override
    public void setAdMaterialLoadListener(
            AdMaterialLoadListener adMaterialLoadListener) {
        mAdMaterialLoadListener = adMaterialLoadListener;
    }

    @Override
    public void setAdPlayStateListener(AdPlayStateListener adPlayStateListener) {
        mAdPlayStateListener = adPlayStateListener;
    }

}